import json
import re
from audioop import reverse

from django.contrib.auth import login, authenticate, logout
from django.shortcuts import render, redirect

# Create your views here.
from django.views import View
from django.http import JsonResponse
from django_redis import get_redis_connection
from pymysql import DatabaseError

from AiJiaHome.utils.fastdfs.fastdfs_storage import FastDFSStorage
from AiJiaHome.utils.response_code import RET
from AiJiaHome.utils.views import LoginRequiredJSONMixin
from users.models import User


class UserLogoutView(LoginRequiredJSONMixin, View):
    '''退出登录'''

    def delete(self, request):
        # 退出登录
        logout(request)
        # 重定向到首页
        response = JsonResponse({'errno': RET.OK, 'errmsg': "用户已退出"})
        # 登录退出清除cookie信息
        response.delete_cookie('username')
        return response


class UserLoginStatusView(View):
    '''获取登录状态'''

    def get(self, request):
        '''获取登录状态'''
        try:
            user = request.user
            context = {"user_id": user.id, "name": user.username}
        except:
            return JsonResponse({"errno": RET.SESSIONERR, "errmsg": "未登录"})

        return JsonResponse({"errno": RET.OK, "errmsg": "OK", "data": context})


class UserLoginView(View):
    '''用户登录界面'''

    def post(self, request):
        '''用户登录界面'''
        # 获得参数
        json_dict = json.loads(request.body.decode())
        mobile = json_dict.get('mobile')
        password = json_dict.get('password')

        # 校验参数
        # 检查参数是否齐全
        if not all([mobile, password]):
            return JsonResponse({'errno': RET.NODATA, 'errmsg': "缺少必传参数"})

        # 判断手机号
        if not re.match(r'^[1][34578][0-9]{9}$', mobile):
            return JsonResponse({'errno': RET.NODATA, 'errmsg': "手机号格式错误"})

        # 判断密码是否是8-20个字符
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return JsonResponse({'errno': RET.NODATA, 'errmsg': "密码格式错误"})

        # 3. 获取登录用户,并查看是否存在
        try:
            if re.match(r'^[1][34578][0-9]{9}$', mobile):
                user = User.objects.get(mobile=mobile)
                username = user.username
            else:
                username = mobile
        except:
            return JsonResponse({'errno': RET.USERERR, 'errmsg': "用户不存在或未激活"})
        # 检查密码是否正确
        user = authenticate(username=username, password=password)
        if user is None:
            return JsonResponse({'errno': RET.USERERR, 'errmsg': "用户不存在或未激活"})

        # 实现状态保持
        login(request, user)
        # 记住用户名,none表示默认两周过期
        request.session.set_expiry(None)
        # 返回响应
        response = JsonResponse({'errno': RET.OK, 'errmsg': "登录成功"})
        # 设置cookie信息
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)
        return response


class UserRegisterView(View):
    '''用户注册'''

    def post(self, request):
        # 1.获得参数
        json_dict = json.loads(request.body.decode())

        mobile = json_dict.get('mobile')
        phonecode_client = json_dict.get('phonecode')
        password = json_dict.get('password')
        password2 = json_dict.get('password2')

        # 校验参数
        # 检查参数是否齐全
        if not all([mobile, phonecode_client, password, password2]):
            return JsonResponse({'errno': RET.NODATA, 'errmsg': "缺少必传参数"})
        # 判断手机号
        if not re.match(r'^[1][34578][0-9]{9}$', mobile):
            return JsonResponse({'errno': RET.NODATA, 'errmsg': "手机号格式错误"})
        # 判断密码是否是8-20个字符
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return JsonResponse({'errno': RET.NODATA, 'errmsg': "密码格式错误"})
        # 判断两次输入密码是否一致
        if password != password2:
            return JsonResponse({'errno': RET.NODATA, 'errmsg': "两次密码不一致"})

        # 判断短信验证码
        redis_conn = get_redis_connection('verify_code')
        phonecode_server = redis_conn.get('sms_code_%s' % mobile)
        if phonecode_server is None:
            # 不存在说明超时,直接返回注册页面
            return JsonResponse({'errno': RET.DBERR, 'errmsg': "短信验证码错误"})

        if phonecode_client != phonecode_server.decode('utf-8'):
            return JsonResponse({'errno': RET.DBERR, 'errmsg': "短信验证码错误"})

        # 检查是否重复注册
        count = User.objects.filter(username=mobile).count()
        if count != 0:
            return JsonResponse({'errno': RET.DBERR, 'errmsg': "手机号已被注册"})

        # 保存用户数据
        try:
            user = User.objects.create_user(username=mobile, password=password, mobile=mobile)
        except DatabaseError:
            return JsonResponse({'errno': RET.DBERR, 'errmsg': "注册失败"})

        # 实现状态保持
        login(request, user)
        # 响应注册结果

        # 重定向返回结果
        response = JsonResponse({'errno': RET.OK, 'errmsg': "注册成功"})
        # 设置cookie信息
        response.set_cookie('username', user.username, max_age=3600 * 24 * 15)
        return response


class UserInfoView(LoginRequiredJSONMixin, View):
    '''获取用户信息'''

    def get(self, request):
        '''获取用户信息'''

        # 获取参数
        user = request.user
        try:
            # 获取用户信息
            context = {
                'name': user.username,
                'avatar_url': user.avatar_url,
                'mobile': user.mobile
            }
        except:
            return JsonResponse({"errno": RET.DBERR, "errmsg": "请求数据库错误"})

        return JsonResponse({"errno": RET.OK, "errmsg": "OK", "data": context})

    def post(self, request):
        # 修改用户名
        # 获得参数
        json_dict = json.loads(request.body.decode())
        name = json_dict.get('name')

        # 检验参数
        if not all([name]):
            return JsonResponse({'errno': RET.NODATA, 'errmsg': "缺少必传参数"})

        if not re.match(r'^[a-zA-Z0-9_-]+$', name):
            return JsonResponse({'errno': RET.NODATA, 'errmsg': "参数错误"})
        # 保存参数
        try:
            request.user.username = name
            request.user.save()
        except Exception:
            return JsonResponse({'errno': RET.DATAERR, 'errmsg': "保存数据库失败"})

        return JsonResponse({'errno': RET.OK, 'errmsg': "OK"})


class UserInfoAvatarView(LoginRequiredJSONMixin, View):
    '''保存用户图形'''

    def post(self, request):
        avatar = request.FILES.get('avatar')
        # 上传用户图片
        try:
            file_id = FastDFSStorage().save(avatar.name, avatar)
            url = FastDFSStorage().url(file_id)
        except Exception:
            return JsonResponse({"errno": RET.DBERR, "errmsg": "上传失败"})

        # 保存用户头像
        try:
            request.user.avatar_url = url
            request.user.save()
        except Exception:
            return JsonResponse({"errno": RET.DBERR, "errmsg": "上传失败"})
        return JsonResponse({"errno": RET.OK, "errmsg": "OK", "data": {"avatar_url": url}})


class UserInfoAuthView(LoginRequiredJSONMixin, View):
    '''设置用户实名信息'''

    def get(self, request):
        # 获取用户
        user = request.user
        try:
            context = {
                'real_name': user.real_name,
                'id_card': user.id_card
            }
        except Exception:
            return JsonResponse({"errno": RET.DBERR, "errmsg": "请求数据库错误"})

        return JsonResponse({"errno": RET.OK, "errmsg": "success", "data": context})

    def post(self, request):
        '''设置新的实名信息'''
        # 接受参数
        json_dict = json.loads(request.body.decode())
        real_name = json_dict.get('real_name')
        id_card = json_dict.get('id_card')

        # 校验参数
        if not all([real_name, id_card]):
            return JsonResponse({'errno': RET.DATAERR, 'errmsg': "缺少必传参数"})

        if not re.match(r'^(?:[\u4E00-\u9FFF]{1,8}·\u4E00-\u9FFF]{1,8})|(?:[\u4E00-\u9FFF]{2,5})$', real_name):
            return JsonResponse({'errno': RET.DATAERR, 'errmsg': "姓名错误"})

        if not re.match(r'^(\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x))$', id_card):
            return JsonResponse({'errno': RET.DATAERR, 'errmsg': "身份证错误"})

        # 保存信息
        try:
            user = request.user
            if user.real_name is None and user.id_card is None:
                user.real_name = real_name
                user.id_card = id_card
                user.save()
            else:
                return JsonResponse({'errno': RET.DBERR, 'errmsg': "已经实名认证"})
        except Exception:
            return JsonResponse({'errno': RET.DBERR, 'errmsg': "修改信息失败"})

        # 返回参数
        return JsonResponse({'errno': RET.OK, 'errmsg': "OK"})
